package com.xxl.job.admin.controller;

import com.xxl.job.admin.core.model.XxlJobUser;
import com.xxl.job.admin.dto.CronJobDetailsDto;
import com.xxl.job.admin.dto.CronJobRequest;
import com.xxl.job.admin.dto.JobResultDTO;
import com.xxl.job.admin.dto.Page;
import com.xxl.job.admin.service.*;
import com.xxl.job.admin.utils.RegexUtil;
import com.xxl.job.core.biz.model.ReturnT;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/cronjobs")
public class CronJobController {

    @Autowired
    private CronJobService cronJobService;

    @Autowired
    private XxlJobExecutorService xxlJobExecutorService;

    @Autowired
    private JobResultService jobResultService;

    @Autowired
    private AuditLogService auditLogService;

    // 查询定时任务列表返回至首页
    @GetMapping("/search")
    public Page<CronJobDetailsDto> searchCronJobs(@RequestParam(required = false) String ip,
                                                  @RequestParam(required = false) String owner,
                                                  @RequestParam(required = false) String systemName,
                                                  @RequestParam(required = false) String serverUser,
                                                  @RequestParam(required = false) String command,
                                                  @RequestParam(defaultValue = "1") int page,
                                                  @RequestParam(defaultValue = "10") int size) {
        return cronJobService.getCronJobDetails(ip, owner, systemName,serverUser,command,page, size);
    }

    @PostMapping("/init")
    public ResponseEntity<Map<String, Object>> initCronJob(HttpServletRequest httpServletRequest) {
        Map<String, Object> response = new HashMap<>();
        // Step 1: 获取执行器ID
        Integer executorId = cronJobService.findExecutorIdByJobHandler("InitCronJobTask");
        if (executorId == null){
            return ResponseEntity.ok(Map.of("success", false,
                    "message", "未找到 JobHandler 对应的执行器 ID: InitCronJobTask"));
        }
        if (executorId <= 0) {
            response.put("success", false);
            response.put("message", "执行器ID获取失败");
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
        }

        // Step 2: 调用执行器，传递调度时间、任务命令和服务器IP
        String sessionId = getSessionIdFromRequest(httpServletRequest); // 获取sessionId
        xxlJobExecutorService.triggerInitCronJobTask(executorId,sessionId);

        response.put("success", true);
        response.put("message", "初始化完成");
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
    }

    // 新增定时任务
    @PostMapping("/add")
    public ResponseEntity<Map<String, Object>> addCronJob(@RequestBody CronJobRequest cronJobRequest,
                                                          HttpServletRequest httpServletRequest) {
        System.out.println("************正在新增任务*********");
        Map<String, Object> response = new HashMap<>();
        try {
            // 获取请求参数
            String addSchedule = cronJobRequest.getSchedule();
            String addCommand = cronJobRequest.getCommand();
            String addServerIp = cronJobRequest.getIp();
            String serverUser = cronJobRequest.getServerUser();
            String verifyUser = cronJobRequest.getVerifyUser();
            String ticketNumber = cronJobRequest.getTicketNumber();
            XxlJobUser User =  (XxlJobUser)httpServletRequest.getAttribute(LoginService.LOGIN_IDENTITY_KEY);
            String currentUser = User.getUsername();
            //  验证调度时间格式（正则校验）
            System.out.println("后端数据"+addSchedule+" "+addCommand+" "+addServerIp);
            if (!RegexUtil.isValidCronExpression(addSchedule)) {
                response.put("success", false);
                response.put("message", "后端校验调度时间格式不正确");
                return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
            }else{
                // 从数据库中获取执行器ID
                Integer executorId = cronJobService.findExecutorIdByJobHandler("AddCronJobTask");
                if (executorId == null){
                    return ResponseEntity.ok(Map.of("success", false,
                            "message", "未找到 JobHandler 对应的执行器 ID: AddCronJobTask"));
                }
                if (executorId <= 0) {
                    response.put("success", false);
                    response.put("message", "执行器ID获取失败");
                    return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
                }
                // Step 2: 调用执行器，传递调度时间、任务命令和服务器IP
                String sessionId = getSessionIdFromRequest(httpServletRequest); // 获取sessionId
                xxlJobExecutorService.triggerDownCronJobTask(executorId,addSchedule,addCommand,addServerIp,sessionId,serverUser);

                // Step 3: 等待回调结果
                JobResultDTO jobResultDTO = jobResultService.waitForExecutionResult(addServerIp, 2, 1000);
                if (jobResultDTO.getSuccess()){
                    System.out.println("新增定时任务");
                    cronJobService.addCronJob(cronJobRequest);
                    Integer jobId = cronJobService.findJobIdByAddWork(addServerIp, addSchedule, addCommand);
                    System.out.println(Long.valueOf(jobId));
                    // 记录日志时保存工单号
                    auditLogService.saveAuditLog(Long.valueOf(jobId), executorId, null, addSchedule,
                            null,addSchedule,currentUser,verifyUser,ticketNumber);
                    response.put("success", true);
                    response.put("message", "定时任务添加成功");
                    return ResponseEntity.ok(response);
                }else {
                    response.put("success", false);
                    response.put("message", "定时任务添加失败");
                    return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            response.put("success", false);
            response.put("message", "定时任务添加失败: " + e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
        }
    }

    //禁用定时任务
    @PostMapping("/disable")
    public ResponseEntity<Map<String, Object>> disableCronJob(@RequestBody Map<String, String> request,
                                                              HttpServletRequest httpServletRequest) {
        System.out.println("************正在禁用任务*********");
        System.out.println("收到禁用任务请求：" + request);
        long jobId = Long.parseLong(request.get("jobId"));
        String schedule = request.get("schedule");
        String command = request.get("command");
        String serverIp = request.get("serverIp");
        String serverUser = request.get("serverUser");
        String verifyUser = request.get("verifyUser");
        String ticketNumber = request.get("ticketNumber");
        XxlJobUser User =  (XxlJobUser)httpServletRequest.getAttribute(LoginService.LOGIN_IDENTITY_KEY);
        String currentUser = User.getUsername();


        CronJobDetailsDto cronJob = cronJobService.findById(jobId);
        Integer status = cronJob.getStatus();
        if (status==0 && schedule.startsWith("#")){
            return ResponseEntity.ok(Map.of("success", false, "message", "该任务已被禁用"));
        }

        // Step 1: 查询执行器ID
        int executorId = cronJobService.findExecutorIdByJobHandler("DownCronJobTask");
        System.out.println("执行器id : "+ executorId);
        // Step 2: 调用执行器，传递调度时间、任务命令和服务器IP

        String sessionId = getSessionIdFromRequest(httpServletRequest);
        xxlJobExecutorService.triggerDownCronJobTask(executorId, schedule, command, serverIp, sessionId,serverUser);

        // Step 3: 等待回调结果
        JobResultDTO jobResultDTO = jobResultService.waitForExecutionResult(serverIp, 2, 500);

        // 如果执行器的回调结果仍然为空，返回错误信息
        if (jobResultDTO.getSuccess()) {
            // Step 4: 更新数据库，启用定时任务
            Map<String, Object> response = new HashMap<>();
            if (jobResultDTO.getSuccess()){
                schedule = "#" + schedule;
                System.out.println("定时任务取消" + schedule);
                cronJobService.updateCronJobStatus(jobId, 0,schedule);  // 更新任务状态为禁用
                // 记录日志时保存工单号
                auditLogService.saveAuditLog(jobId, executorId, request.get("schedule"), schedule,
                        request.get("command"),command,currentUser,verifyUser,ticketNumber);
                response.put("success", true);
                response.put("message", "任务已禁用");
                return ResponseEntity.ok(response);
            }else {
                response.put("success", false);
                response.put("message", "任务禁用失败");
                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
            }
        }else{
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(Map.of("success", false, "message", "未能从执行器获得回调结果"));
        }
    }

    //启用定时任务
    @PostMapping("/enable")
    public ResponseEntity<Map<String, Object>> enableCronJob(@RequestBody Map<String, String> request,
                                                              HttpServletRequest httpServletRequest) {
        System.out.println("************正在启用任务*********");
        System.out.println("收到启用任务请求：" + request);
        long jobId = Long.parseLong(request.get("jobId"));
        String schedule = request.get("schedule");
        String command = request.get("command");
        String serverIp = request.get("serverIp");
        String serverUser = request.get("serverUser");
        String verifyUser = request.get("verifyUser");
        String ticketNumber = request.get("ticketNumber");
        XxlJobUser User =  (XxlJobUser)httpServletRequest.getAttribute(LoginService.LOGIN_IDENTITY_KEY);
        String currentUser = User.getUsername();

        CronJobDetailsDto cronJob = cronJobService.findById(jobId);
        Integer status = cronJob.getStatus();
        if (status==1 && !schedule.startsWith("#")){
            return ResponseEntity.ok(Map.of("success", false, "message", "该任务已启用无需重复启用"));
        }

        // Step 1: 查询执行器ID
        Integer executorId = cronJobService.findExecutorIdByJobHandler("UpCronJobTask");
        if (executorId == null){
            return ResponseEntity.ok(Map.of("success", false, "message", "未找到 JobHandler 对应的执行器 ID: UpCronJobTask"));
        }

        System.out.println("执行器id : "+ executorId);
        // Step 2: 调用执行器，传递调度时间、任务命令和服务器IP

        String sessionId = getSessionIdFromRequest(httpServletRequest);
        xxlJobExecutorService.triggerDownCronJobTask(executorId, schedule, command,
                serverIp, sessionId,serverUser);

        // Step 3: 等待回调结果
        JobResultDTO jobResultDTO = jobResultService.waitForExecutionResult(serverIp, 2, 500);

        // 如果执行器的回调结果仍然为空，返回错误信息
        if (jobResultDTO == null) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(Map.of("success", false, "message", "未能从执行器获得回调结果"));
        }

        // Step 4: 更新数据库，启用定时任务
        Map<String, Object> response = new HashMap<>();
        if (jobResultDTO.getSuccess()){
            schedule=schedule.replace("#","");
            System.out.println("定时任务启用" + schedule);
            cronJobService.updateCronJobStatus(jobId, 1,schedule);  // 更新任务状态为禁用
            // 记录日志时保存工单号
            auditLogService.saveAuditLog(jobId, executorId, request.get("schedule"), schedule,
                    request.get("command"),command,currentUser,verifyUser,ticketNumber);
            response.put("success", true);
            response.put("message", "任务已启用");
            return ResponseEntity.ok(response);
        }else {
            response.put("success", false);
            response.put("message", "任务启用失败");
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
        }
    }

    //编辑按钮查询接口
    @GetMapping("/detail/{jobId}")
    public ResponseEntity<Map<String, Object>> getCronJobDetails(@PathVariable("jobId") Long jobId) {
        System.out.println("收到查询请求ID" + jobId);
        // 调用服务层查询任务
        CronJobDetailsDto cronJob = cronJobService.findById(jobId);

        if (cronJob != null) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String formattedDate = cronJob.getUpdatedAt() != null ? sdf.format(cronJob.getUpdatedAt()) : "";
            // 返回任务的详细信息
            Map<String, Object> response = new HashMap<>();
            response.put("success", true);
            response.put("jobId", cronJob.getId());
            response.put("ip", cronJob.getIp());
            response.put("owner", cronJob.getOwner());
            response.put("systemName", cronJob.getSystemName());
            response.put("schedule", cronJob.getSchedule());
            response.put("command", cronJob.getCommand());
            response.put("serverUser", cronJob.getServerUser());
            response.put("status", cronJob.getStatus());
            response.put("uptime", formattedDate);
            System.out.println(response);
            return ResponseEntity.ok(response);
        } else {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
        }
    }
    //执行编辑操作请求
    @PostMapping("/update")
    public ResponseEntity<Map<String, Object>> updateCronJob(@RequestBody Map<String, String> request,
                                                             HttpServletRequest httpServletRequest) {
        System.out.println("************正在编辑任务*********");
        Map<String, Object> response = new HashMap<>();

        try {
            // 获取请求参数
            long jobId = Long.parseLong(request.get("jobId"));
            String newSchedule = request.get("schedule");
            String newCommand = request.get("command");
            String owner = request.get("owner");
            String systemName = request.get("systemName");
            String serverIp = request.get("serverIp");
            String serverUser = request.get("serverUser");
            //找到被修改的定时任务源调度和命令
            CronJobDetailsDto cronJob = cronJobService.findById(jobId);
            String schedule = cronJob.getSchedule();
            String command = cronJob.getCommand();
            String verifyUser = request.get("verifyUser");
            String ticketNumber = request.get("ticketNumber");
            XxlJobUser User =  (XxlJobUser)httpServletRequest.getAttribute(LoginService.LOGIN_IDENTITY_KEY);
            String currentUser = User.getUsername();
            System.out.println(currentUser+" 二次验证: " + verifyUser + " 工单号: " + ticketNumber);


            //  验证调度时间格式（正则校验）
            System.out.println("后端数据"+response);
            if (!RegexUtil.isValidCronExpression(newSchedule)) {
                response.put("success", false);
                response.put("message", "后端校验调度时间格式不正确");
                return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
            }else{
                // Step 1: 查询执行器ID
                Integer executorId = cronJobService.findExecutorIdByJobHandler("UpdateCronJobTask");
                if (executorId == null){
                    return ResponseEntity.ok(Map.of("success", false, "message", "未找到 JobHandler 对应的执行器 ID: UpdateCronJobTask"));
                }

                System.out.println("执行器id : "+ executorId);
                // Step 2: 调用执行器，传递调度时间、任务命令和服务器IP

                String sessionId = getSessionIdFromRequest(httpServletRequest);
                xxlJobExecutorService.triggerUpdateCronJobTask(executorId, schedule,newSchedule,command,
                        newCommand,serverIp,sessionId,serverUser);

                // Step 3: 等待回调结果
                JobResultDTO jobResultDTO = jobResultService.waitForExecutionResult(serverIp, 2, 1000);

                if (jobResultDTO.getSuccess()){
                    //更新数据库中的定时任务信息
                    //更新前先判断是否改为生效
                    Integer newStatus = 0;
                    if (newSchedule.startsWith("#")){
                        newStatus = 0;
                    }else {
                        newStatus = 1;
                    }
                    schedule=schedule.replace("#","");
                    System.out.println("定时任务取消" + schedule);
                    cronJobService.updateCronJob(jobId, newSchedule, newCommand, owner, systemName,newStatus);  // 更新任务状态为禁用
                    // 记录日志时保存工单号
                    auditLogService.saveAuditLog(jobId, executorId, schedule, newSchedule,
                            command,newCommand,currentUser,verifyUser,ticketNumber);
                    response.put("success", true);
                    response.put("message", "任务更新成功");
                    return ResponseEntity.ok(response);
                }else {
                    response.put("success", false);
                    response.put("message", "任务更新失败");
                    return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
            response.put("success", false);
            response.put("message", "任务更新失败: " + e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
        }
    }

    // 从 HttpServletRequest 中获取 Cookie 并提取 sessionId
    private String getSessionIdFromRequest(HttpServletRequest request) {
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if ("XXL_JOB_LOGIN_IDENTITY".equals(cookie.getName())) {
                    return cookie.getValue();
                }
            }
        }
        return null;
    }
}
